#include <tinx/memory.h>
#include <tinx/device.h>
#include <tinx/debug.h>
#include <tinx/vsprintf.h>
#include <tinx/string.h>

#define RAMDISK_NR 4

typedef struct ramdisk_t
{
    void *data;
    u32 size;
} ramdisk_t;

static ramdisk_t ramdisks[RAMDISK_NR];

int ramdisk_ioctl(ramdisk_t *disk, int cmd, void *args, int flags)
{
    switch (cmd)
    {
    case DEV_CMD_SECTORS_START:
        return EOK;
    case DEV_CMD_SECTORS_COUNT:
        return disk->size / SECTOR_SIZE;
    }
    return EOF;
}

int ramdisk_read(ramdisk_t *disk, void *buf, int count, int idx)
{
    u32 sectors = disk->size / SECTOR_SIZE;
    u32 start = idx * SECTOR_SIZE + (u32)disk->data;
    if ((count + idx) > sectors)
        count = sectors - idx;
    u32 len = count * SECTOR_SIZE;
    memcpy(buf, (void *)start, len);
    return EOK;
}

int ramdisk_write(ramdisk_t *disk, void *buf, int count, int idx)
{
    u32 sectors = disk->size / SECTOR_SIZE;
    u32 start = idx * SECTOR_SIZE + (u32)disk->data;
    if ((count + idx) > sectors)
        count = sectors - idx;
    u32 len = count * SECTOR_SIZE;
    memcpy((void *)start, buf, len);
    return EOK;
}

void ramdisk_init()
{
    u32 size = KERNEL_RAMDISK_SIZE / RAMDISK_NR;
    void *addr = (void *)KERNEL_RAMDISK_ADDR;

    char name[32];

    for (size_t i = 0; i < RAMDISK_NR; i++)
    {
        ramdisk_t *disk = &ramdisks[i];
        disk->data = addr;
        disk->size = size;
        sprintf(name, "md%c", i + 'a');

        // 注册设备
        device_create(
            DEV_TYPE_BLOCK, DEV_FLAG_RAMDISK, -1, name, disk,
            ramdisk_write, ramdisk_read, ramdisk_ioctl);

        addr += size;
    }
}